package jp.sourceforge.akjrcp.text_douga.video;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import jp.sourceforge.akjrcp.text_douga.DougaSystem;
import jp.sourceforge.akjrcp.text_douga.VideoData;
import jp.sourceforge.akjrcp.text_douga.VideoWriter;
import jp.sourceforge.akjrcp.util.image.ImageUtils;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sun.awt.image.ByteArrayImageSource;

public class VideoUtils {
	public static Log log=LogFactory.getLog(VideoUtils.class);
	//copy jpeg
	//return writed;
	public static int copyVideo(String ffmpegPath,String inputPath,double start,double duration,File exportDir,int startIndex,double fps,int width,int height,int maxframe) throws IOException{
		int writed=0;
		
		VideoImageInput videoInput=new VideoImageInput(ffmpegPath,inputPath,start,duration);
		videoInput.setFps(fps);
		videoInput.setWidth(width);
		videoInput.setHeight(height);
		
		JpegKeeper jpegKeeper=videoInput.getJpegKeeper();
		videoInput.startInput();
		
		byte[] bytes;
		while((bytes=jpegKeeper.nextImage())!=null){
			if(DougaSystem.cancelling){
				log.info("dougasystem cancelled");
				break;
			}
			
			File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			writed++;
			FileUtils.writeByteArrayToFile(jpegFile, bytes);
			log.trace("write:"+writed);
			if(writed==maxframe){
				videoInput.setCanceling(true);
				break;
			}
		}
		
		return writed;
	}
	
	public static int copyVideo(VideoData videoData,VideoWriter writer,String ffmpegPath,String inputPath,double start,double duration,double fps,int width,int height) throws IOException{
		int writed=0;
		
		VideoImageInput videoInput=new VideoImageInput(ffmpegPath,inputPath,start,duration);
		videoInput.setFps(fps);
		videoInput.setWidth(width);
		videoInput.setHeight(height);
		
		JpegKeeper jpegKeeper=videoInput.getJpegKeeper();
		videoInput.startInput();
		
		byte[] bytes=null;
		BufferedImage img=null;
		boolean finished=false;
		while((bytes=jpegKeeper.nextImage())!=null){
			if(DougaSystem.cancelling){
				log.info("dougasystem cancelled");
				break;
			}
			
			//File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			//FileUtils.writeByteArrayToFile(jpegFile, bytes);
			
			
			if(img!=null){
				finished=writer.writeFrame(videoData, img);
				writed++;
				if(finished){
					videoInput.setCanceling(true);
					break;
				}
			}
			
			img=ImageIO.read(new ByteArrayInputStream(bytes));
			log.trace("write:"+writed);
		}
		
		if(!finished && img!=null){
			writer.writeFrame(videoData, img);
			writed++;
		}
		
		return writed;
	}
	
	public static int copyImage(BufferedImage image,File exportDir,int startIndex,int frames) throws IOException{
		int writed=0;
		
			for(int i=0;i<frames;i++){
				if(DougaSystem.cancelling){
					log.info("dougasystem cancelled");
					break;
				}
			File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			writed++;
			ImageUtils.writeJpegWithQuality(image, jpegFile, 1.0f);
			}
		
		
		return writed;
	}
	
	public static int copyImage(BufferedImage image,VideoData videoData,VideoWriter writer,int frames) throws IOException{
		int writed=0;
		
			for(int i=0;i<frames;i++){
				if(DougaSystem.cancelling){
					log.info("dougasystem cancelled");
					break;
				}
				writer.writeFrame(videoData, image);//TODO care ends.
				writed++;
			}
		
		
		return writed;
	}
	
	public static int loopVideo(String ffmpegPath,String input,double start,double duration,int looptime,double padtime,int padcolor,boolean cutInLoop,File exportDir,int startIndex,double fps,int width,int height,int maxframe) throws IOException{
		if(looptime==0){
			log.warn("loop is 0");
			return 0;
		}
		if(looptime==DougaSystem.FOREEVER && maxframe==0){
			log.warn("it's never stop");
			return 0;
		}
		log.info("cutInLoop:"+cutInLoop);
		//first loop;
		int firstWrite=copyVideo(ffmpegPath,input,start,duration,exportDir,startIndex,fps,width,height,maxframe);
		if(looptime==1){
			return firstWrite;
		}
		log.info("first write:"+firstWrite);
		//finish max;
		int writed=firstWrite;
		if(writed>=maxframe && maxframe>0){//0 don't care
			return writed;
		}
		
		
		int looped=1;//done already 1 time
		
		
		boolean loop=true;
		LOOP:while(loop){
		
			//pad first
			if(loop && padtime>0){
				int colorframe=(int) (fps*padtime);
				for (int i = 0; i < colorframe; i++) {
					if(DougaSystem.cancelling){
						log.info("dougasystem cancelled");
						break LOOP;
					}
					String colorPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo
					writeColorImage(width,height,colorPath,padcolor);
					writed++;
					if(writed==maxframe){//never 0
						break LOOP;//on pad any way break;
					}
				}
				log.info("pad:"+colorframe+" color"+padcolor);
				}
			
		for(int i=0;i<firstWrite;i++){
			//copy
			String srcPath=exportDir.getAbsolutePath()+"\\"+toFileName("", startIndex+i, 5, "jpg");//todo;
			String destPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo;
			FileUtils.copyFile(new File(srcPath), new File(destPath));
			//check max?
			writed++;
			if(writed==maxframe){//never 0
				if(cutInLoop){
					break LOOP;
				}else{
					loop=false;
				}
				
			}
		}
		
		looped++;
		if(looped==looptime){
			loop=false;
			}
		

		
		log.info("loop:"+looped+" write"+writed);
		}
		
		return writed;
	}
	

	public static int loopVideo(VideoData videoData,VideoWriter writer,String ffmpegPath,String input,double start,double duration,int looptime,double padtime,int padcolor,boolean cutInLoop,double fps,int width,int height) throws IOException{
		if(looptime==0){
			log.warn("loop is 0");
			return 0;
		}
		if(looptime==DougaSystem.FOREEVER && writer.getMaxFrame()==0){
			log.warn("it's never stop");
			return 0;
		}
		log.info("cutInLoop:"+cutInLoop);
		int startIndex=writer.getWrited()+1;
		int maxframe=Math.max(0, writer.getMaxFrame()-writer.getWrited());
		//first loop;
		int firstWrite=copyVideo(ffmpegPath,input,start,duration,writer.getWorkingDir(),startIndex,fps,width,height,maxframe);
		//
		
		for(int i=0;i<firstWrite;i++){
			File frame=writer.getWorkingFrameFile(i+startIndex);
			BufferedImage image=ImageIO.read(frame);
			writer.writeFrame(videoData, image);
		}
		
		//
		if(looptime==1){
			return firstWrite;
		}
		log.info("first write:"+firstWrite);
		//finish max;
		int writed=firstWrite;
		if(writed>=maxframe && maxframe>0){//0 don't care
			return writed;
		}
		
		
		int looped=1;//done already 1 time
		
		
		boolean loop=true;
		LOOP:while(loop){
		
			//pad first
			if(loop && padtime>0){
				int colorframe=(int) (fps*padtime);
				for (int i = 0; i < colorframe; i++) {
					if(DougaSystem.cancelling){
						log.info("dougasystem cancelled");
						break LOOP;
					}
					BufferedImage colorImage=makeColorImage(width,height,padcolor);
					//writeColorImage(width,height,colorPath,padcolor);
					writer.writeFrame(videoData, colorImage);
					writed++;
					if(writed==maxframe){//never 0
					
						break LOOP;//on pad any way break;
					}
				}
				log.info("pad:"+colorframe+" color"+padcolor);
				}
			
		for(int i=0;i<firstWrite;i++){
			//copy
			//srcPath=exportDir.getAbsolutePath()+"\\"+toFileName("", startIndex+i, 5, "jpg");//todo;
			File frame=writer.getWorkingFrameFile(i+startIndex);
			BufferedImage image=ImageIO.read(frame);
			//String destPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo;
			//FileUtils.copyFile(new File(srcPath), new File(destPath));
			//check max?
			writer.writeFrame(videoData, image);
			writed++;
			if(writed==writer.getMaxFrame()){//never 0
				if(cutInLoop){
					break LOOP;
				}else{
					loop=false;
				}
				
			}
		}
		
		looped++;
		if(looped==looptime){
			loop=false;
			}
		

		
		log.info("loop:"+looped+" write"+writed);
		}
		
		return writed;
	}

	public static void writeColorImage(int width,int height,String path,int color) throws IOException{
		ImageIO.write(makeColorImage(width,height,color), "jpeg", new File(path));
	}
	public static BufferedImage makeColorImage(int width,int height,int color){
		BufferedImage bimage=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		Graphics g=bimage.getGraphics();
		g.setColor(new Color(color));
		g.fillRect(0, 0, width, height);
		return bimage;
	}
	
	public static String toFileName(String header,int index,int digits,String extension){
		String value=header;
		String c=""+index;
		while(c.length()<digits){
			c="0"+c;
		}
		value+=c;
		value+="."+extension;
		return value;
	}
}
